using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.Service.ApiJob.Dto;
using Admin.NET.Core;
using Admin.NET.Core.Service;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SqlSugar;
using Yitter.IdGenerator;

namespace Admin.NET.Application.Service.ApiJob;

[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class ApiJobService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SysCacheService _sysCacheService;

	private readonly SqlSugarRepository<ApiJobInfo> _rep;

	private readonly SysJobService _jobService;

	public ApiJobService(SqlSugarRepository<ApiJobInfo> rep, SysCacheService sysCacheService, SysJobService jobService)
	{
		_rep = rep;
		_sysCacheService = sysCacheService;
		_jobService = jobService;
	}

	/// <summary>
	/// 获取作业
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpGet("/job/apijob/page")]
	public async Task<dynamic> ModelPage([FromQuery] JobQuaryInput input)
	{
		ISugarQueryable<ApiJobInfo> query = _rep.Context.Queryable<ApiJobInfo>().WhereIF(!string.IsNullOrWhiteSpace(input.Name), (ApiJobInfo u) => u.Name.Contains(input.Name)).WhereIF(input.State.HasValue, (ApiJobInfo u) => (int?)u.State == input.State);
		query = query.OrderBuilder(input);
		return await query.ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 新增作业
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/job/apijob/add")]
	public async Task AddModel(ApiJobInfo input)
	{
		string url = "http://127.0.0.1:5005/job/operateJob";
		if (input.OperateCode == 3)
		{
			ElectricityPriceRule entity = input.MeterPrice.Adapt<ElectricityPriceRule>();
			entity.Id = YitIdHelper.NextId();
			await _rep.Context.Insertable(entity).ExecuteCommandAsync();
			input.MeterRuleId = entity.Id;
		}
		input = await _rep.InsertReturnEntityAsync(input);
		await CreateJob(url, input);
	}

	/// <summary>
	/// 修改作业
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/job/apijob/edit")]
	public async Task EditModel(ApiJobInfo input)
	{
		if (input.OperateCode == 3 && input.MeterRuleId.HasValue)
		{
			ElectricityPriceRule entity = input.MeterPrice.Adapt<ElectricityPriceRule>();
			await _rep.Context.Updateable(entity).ExecuteCommandAsync();
		}
		await DeleteJob(input);
		string url = "http://127.0.0.1:5005/job/operateJob";
		await CreateJob(url, input);
		await _rep.UpdateAsync(input);
	}

	private async Task DeleteJob(ApiJobInfo task)
	{
		DeleteJobDetailInput job = new DeleteJobDetailInput
		{
			JobId = task.Id + "_job"
		};
		await _jobService.DeleteJobDetail(job);
	}

	/// <summary>
	/// 删除作业
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/job/apijob/delete")]
	public async Task DeleteModel(ApiJobInfo input)
	{
		await DeleteJob(input);
		await _rep.DeleteAsync(input);
	}

	private async Task CreateJob(string url, ApiJobInfo job)
	{
		if (job.State != 0)
		{
			string cron = CreatCron(job);
			AddJobDetailInput input = new AddJobDetailInput
			{
				Concurrent = false,
				CreateType = JobCreateTypeEnum.Http,
				GroupName = "meter",
				JobId = job.Id + "_job",
				ScriptCode = "",
				Description = job.Name
			};
			var body = new
			{
				id = job.Id,
				Code = job.OperateCode,
				meterInfo = job.MeterInfo,
				meterPrice = job.MeterPrice,
				operateCode = job.OperateCode,
				meterRuleId = job.MeterRuleId
			};
			PropertyHttpJob httpJon = new PropertyHttpJob
			{
				ClientName = "HttpJob",
				EnsureSuccessStatusCode = true,
				HttpMethod = new PropertyHttpJobMethod
				{
					Method = "POST"
				},
				RequestUri = url,
				Body = JsonConvert.SerializeObject(body)
			};
			PropertyJob properties = new PropertyJob
			{
				HttpJob = JsonConvert.SerializeObject(httpJon)
			};
			input.Properties = JsonConvert.SerializeObject(properties);
			await _jobService.AddJobDetail(input);
			AddJobTriggerInput input2 = new AddJobTriggerInput
			{
				Args = "\"" + cron + "\",3",
				Description = "",
				JobId = input.JobId,
				MaxNumberOfErrors = 1L,
				MaxNumberOfRuns = 0L,
				ResetOnlyOnce = true,
				RetryTimeout = 1000,
				RunOnStart = false,
				StartNow = true,
				TriggerId = job.Id + "_job_trigger",
				TriggerType = "Furion.Schedule.CronTrigger"
			};
			await _jobService.AddJobTrigger(input2);
		}
	}

	private string CreatCron(ApiJobInfo tmp)
	{
		string cron = "";
		if (tmp.Type == 0)
		{
			cron = (tmp.Second ?? "0") + " " + tmp.Minute + " " + tmp.Hour + " " + tmp.Day + " " + tmp.Month + " ? " + tmp.Year;
		}
		else if (tmp.Type == 1)
		{
			cron = (tmp.Second ?? "0") + " " + tmp.Minute + " " + tmp.Hour + " * * ? *";
		}
		else if (tmp.Type == 2)
		{
			cron = (tmp.Second ?? "0") + " " + tmp.Minute + " " + tmp.Hour + " ? * " + tmp.Weekly + " *";
		}
		else if (tmp.Type == 3)
		{
			cron = (tmp.Second ?? "0") + " " + tmp.Minute + " " + tmp.Hour + " " + tmp.Day + " * ? *";
		}
		if (string.IsNullOrWhiteSpace(cron))
		{
			throw Oops.Bah("触发时间有误，请重新选择");
		}
		return cron;
	}
}
